package com.yc.cloud.portal.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.yc.cloud.api.enums.OrderStatusEnums;
import com.yc.cloud.api.enums.OrderTypeEnums;
import com.yc.cloud.common.basic.dto.BasePageReqDTO;
import com.yc.cloud.common.basic.exception.Asserts;
import com.yc.cloud.common.basic.utils.SnowflakeIdGenerator;
import com.yc.cloud.common.pay.constants.PayErrorTips;
import com.yc.cloud.common.pay.dto.request.WxCreateOrderParam;
import com.yc.cloud.common.pay.enums.PayTypeEnums;
import com.yc.cloud.common.pay.service.WxPayService;
import com.yc.cloud.entity.Order;
import com.yc.cloud.mapper.OrderMapper;
import com.yc.cloud.portal.common.PortalErrorTips;
import com.yc.cloud.portal.request.OrderCreateParam;
import com.yc.cloud.portal.service.MemberAccountService;
import com.yc.cloud.portal.service.OrderService;
import com.yc.cloud.portal.service.ProductService;
import com.yc.cloud.portal.vo.OrderCreateVo;
import com.yc.cloud.security.utils.MemberUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author Yancy
 * @since 2024-01-18
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    private final SnowflakeIdGenerator snowflakeIdGenerator;

    private final WxPayService wxPayService;

    private final MemberAccountService memberAccountService;

    private final ProductService productService;

    public OrderServiceImpl(WxPayService wxPayService, MemberAccountService memberAccountService, ProductService productServic) {
        snowflakeIdGenerator = new SnowflakeIdGenerator(1L);
        this.wxPayService = wxPayService;
        this.memberAccountService = memberAccountService;
        this.productService = productServic;
    }

    @Override
    public IPage<Order> list(BasePageReqDTO queryParam) {
        val query = new QueryWrapper<Order>();
        IPage<Order> page;
        query.eq(Order.CREATE_BY, MemberUtils.getCurrentUseId());
        //排序
        if (StrUtil.isNotEmpty(queryParam.getSortBy())) {
            if (BasePageReqDTO.ORDER_DESC.equals(queryParam.getOrder())) {
                query.orderByDesc(Order.ID);
            } else if (BasePageReqDTO.ORDER_ASC.equals(queryParam.getOrder())) {
                query.orderByAsc(Order.ID);
            }
        }
        //模糊查询
        if (StrUtil.isNotEmpty(queryParam.getKeyword())) {
            query.and(queryWrapper -> {

            });
        }
        //分页
        if (queryParam.getPage()) {
            page = new Page<>(queryParam.getPageNum(), queryParam.getPageSize(), true);
        } else {
            page = new Page<>(queryParam.getPageNum(), baseMapper.selectCount(query), true);
        }
        return baseMapper.selectPage(page, query);
    }

    @Override
    public OrderCreateVo create(OrderCreateParam param) {
        //先校验下产品信息是否正确
        val product = productService.getById(param.getProductId());
        if (product == null) {
            Asserts.fail(PortalErrorTips.PRODUCT_NOT_EXIST);
        }
        val order = new Order();
        BeanUtils.copyProperties(param, order);
        val orderNo = generateOrderNo();
        order.setOrderNo(orderNo);
        // val price = getPriceByOrderType(param.getType());
        // order.setPrice(product.getPrice());
        order.setStatus(Integer.parseInt(OrderStatusEnums.NO_PAY.getCode()));
        order.setPrice(product.getPrice());
        order.setDuration(product.getDuration());
        order.setDescription(product.getName());
//        order.setCreateBy(2L);
//        order.setUpdateBy(2L);
        val saveFlag = save(order);
        if (saveFlag) {
            val vo = new OrderCreateVo();
            val prepay = createThirdPartOrder(order);
            vo.setOrder(order);
            vo.setPrepay(prepay);
            return vo;
        }
        return null;
    }

    private PrepayWithRequestPaymentResponse createThirdPartOrder(Order order) {
        if (PayTypeEnums.WECHAT.getCode().equals(String.valueOf(order.getPayType()))) {
            val payParam = new WxCreateOrderParam();
            payParam.setOrderNo(order.getOrderNo());
            payParam.setAmount(order.getPrice());
            payParam.setDescription(order.getDescription());
            //TODO 这块后期需要做调整，根据不同的平台设置
            payParam.setOpenId(MemberUtils.getCurrentUserName());
            return wxPayService.createOrder(payParam);
        }
        return null;
    }

    @Override
    public Order get(Long id) {
        return getById(id);
    }

    @Override
    public boolean delete(Long id) {
        return removeById(id);
    }

    @Override
    public String payNotify(HttpServletRequest request) {
        val payNotifyParserDto = wxPayService.payNotifyParser(request);
        String WX_RETURN_CODE_FAILED = "FAILED";
        if (payNotifyParserDto == null) {
            return convertPayNotifyResult(WX_RETURN_CODE_FAILED, PayErrorTips.ORDER_PAY_INFO_PARSER_FAILED);
        }
        //先校验订单信息是否正确,例如价格
        val order = getByOrderNo(payNotifyParserDto.getOrderNo());
        if (order == null) {
            return convertPayNotifyResult(WX_RETURN_CODE_FAILED, PayErrorTips.ORDER_NO_NOT_EXIST);
        }
        //校验订单金额和这次支付金额是否一致
        if (!Objects.equals(order.getPrice(), payNotifyParserDto.getAmount())) {
            return convertPayNotifyResult(WX_RETURN_CODE_FAILED, PayErrorTips.ORDER_AMOUNT_DIS_MATCH);
        }
        //订单状态是否处于未支付
        if (!OrderStatusEnums.NO_PAY.getCode().equals(String.valueOf(order.getStatus()))) {
            return convertPayNotifyResult(WX_RETURN_CODE_FAILED, PayErrorTips.ORDER_STATUS_ERROR);
        }
        //在查询下订单是否支付成功
        val queryOrderByOutTradeNoDto = wxPayService.queryOrderByOutTradeNo(payNotifyParserDto.getOrderNo());
        if (queryOrderByOutTradeNoDto == null || !queryOrderByOutTradeNoDto.isPaySuccess()) {
            return convertPayNotifyResult(WX_RETURN_CODE_FAILED, PayErrorTips.ORDER_PAY_FAILED);
        }
        //修改业务订单信息
        order.setStatus(Integer.parseInt(OrderStatusEnums.PAY.getCode()));
        order.setTransactionId(payNotifyParserDto.getTransactionId());
        order.setPayTime(LocalDateTime.now());
        order.setUpdateBy(order.getCreateBy());
        log.info("修改订单" + order.getOrderNo() + "状态...");
        val flag = updateById(order);
        if (!flag) {
            return convertPayNotifyResult(WX_RETURN_CODE_FAILED, PayErrorTips.ORDER_STATUS_UPDATE_FAILED);
        }
        //支付成功
        log.info("修改订单" + order.getOrderNo() + "状态成功");
        val memberId = order.getCreateBy();
        val duration = order.getDuration() == null ? 0 : order.getDuration();
        val addVipExpireFlag = memberAccountService.addMemberVipExpireTime(memberId, duration, 0);
        if (!addVipExpireFlag) {
            log.warn("用户[{}],支付成功,但修改会员过期时间失败", memberId);
        }
        String WX_RETURN_CODE_SUCCESS = "SUCCESS";
        log.info("支付回调处理成功...");
        return convertPayNotifyResult(WX_RETURN_CODE_SUCCESS, PayErrorTips.ORDER_PAY_SUCCESS);

    }

    @Override
    public boolean cancelOrder(Long id) {
        //先查询订单是否是该用户的
        val order = getById(id);
        if (order == null) {
            Asserts.fail(PortalErrorTips.ORDER_NOT_EXIST);
        }
        if (!Objects.equals(order.getCreateBy(), MemberUtils.getCurrentUseId())) {
            Asserts.fail(PortalErrorTips.ORDER_OWNER_DIS_MATCH);
        }
        order.setStatus(Integer.parseInt(OrderStatusEnums.CANCEL.getCode()));
        return updateById(order);
    }

    @Override
    public List<Order> listByOrderStatus(String orderStatus) {
        return baseMapper.selectList(new QueryWrapper<Order>().eq(Order.STATUS, orderStatus));
    }

    private String convertPayNotifyResult(String returnCode, String returnMsg) {
        //TODO 还需要修改用户相关信息
        val returnMap = new HashMap<String, String>(2);
        returnMap.put("return_code", returnCode);
        returnMap.put("return_msg", returnMsg);
        return JSONUtil.toJsonStr(returnMap);
    }


    private Order getByOrderNo(String orderNo) {
        return baseMapper.selectOne(new QueryWrapper<Order>().eq(Order.ORDER_NO, orderNo));
    }

    @Override
    public Order update(Long id, Order param) {
        val order = new Order();
        BeanUtils.copyProperties(param, order);
        order.setId(id);
        val updateFlag = updateById(order);
        return updateFlag ? order : null;
    }


    @Override
    public Order convertVo(Order order) {
        if (order == null) {
            return null;
        }
        val vo = new Order();
        BeanUtils.copyProperties(order, vo);
        return vo;
    }


    private String generateOrderNo() {
        val snowflakeId = snowflakeIdGenerator.generateId();
        val now = DateUtil.format(new Date(), "yyyyMMddhhmmss");
        return now + snowflakeId;
    }

    /**
     * 根据订单类型获取对应的价格
     *
     * @param orderType 订单类型
     * @return 实际价格
     */
    private Integer getPriceByOrderType(String orderType) {
        if (OrderTypeEnums.VIP.getCode().equals(orderType)) {
            return 1;
        }
        return 0;
    }

}
